<!DOCTYPE html>
<title>Test that progress events are generated during loading of media resource.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../../media-resources/media-file.js"></script>
<video></video>
<script>
async_test(function(t) {
    var video = document.querySelector('video');
    video.onerror = t.unreached_func();

    // Given long enough duration, We should not reach ended playback state.
    video.onended = t.unreached_func();

    // Tuned throttling should not induce player stall or suspended load.
    video.onstalled = t.unreached_func();
    video.onsuspend = t.unreached_func();
    video.onwaiting = t.unreached_func();

    var progressCount = 0;
    var lastProgressEventTime = 0;

    video.onprogress = t.step_func(function() {
        // Implementations can vary the frequency within tolerance,
        // so we must protect against flaky logs.
        // Remain silent here unless failure detected.
        assert_equals(video.networkState, HTMLMediaElement.NETWORK_LOADING);
        progressCount++;
        lastProgressEventTime = window.performance.now();
    });

    video.oncanplay = t.step_func(function() {
        video.oncanplay = null;
        // Begin video playback to mitigate flakiness due to
        // implementations suspending load on limited buffer capacity.
        video.play();
    });

    var progressCountAtLastCheck = 0;
    var checkCount = 0;
    // Spec requires 350ms +/- 200ms minimum 'progress' event interval when loading.
    var maxProgressFiringIntervalInMS = 550;
    // Multiple 'progress' events may fire within spec's tolerance window.
    var maxProgressCountIncrease = 3;
    function checkProgressCount() {
        // Implementations can vary the frequency within tolerance, so we must protect against flakiness.
        // Keep progressCount values involved in checks here out of report unless failure detected.
        var progressCountDelta = progressCount - progressCountAtLastCheck;
        assert_greater_than(progressCountDelta, 0, 'at least one progress event was fired');
        assert_less_than_equal(progressCountDelta, maxProgressCountIncrease, 'too many progress events were not fired');

        if (++checkCount == 3) {
            t.done();
            return;
        }

        progressCountAtLastCheck = progressCount;
        var msSinceLastProgressEvent = window.performance.now() - lastProgressEventTime;
        var msUntilNextCheck = maxProgressFiringIntervalInMS - msSinceLastProgressEvent;
        assert_greater_than(msUntilNextCheck, 0, 'Progress Event delay');

        setTimeout(t.step_func(checkProgressCount), msUntilNextCheck);
    }

    video.onloadstart = t.step_func(function() {
        // No 'progress' event should fire prior to 'loadstart'.
        assert_equals(progressCount, 0, 'No progress event fired before load event');
        setTimeout(t.step_func(checkProgressCount), maxProgressFiringIntervalInMS);
    });

    var mediaFile = 'resources/test.ogv';
    var mimeType = mimeTypeForFile(mediaFile);
    // Assumes minimum file size selected is > 100 kB.
    // At least 4*maxProgressFiringIntervalInMS is how long we want to stretch the full
    // loading, because we perform checks after 3 of these intervals while still
    // loading. 100 kB over 2.2 seconds is 45 kBps.
    var kBps = 45;

    video.src = 'video-throttled-load.cgi' + '?name=' + mediaFile + '&throttle=' + kBps + '&type=' + mimeType;
});
</script>